package com.literaryfamily.literaryfamily.service.book;

import com.literaryfamily.literaryfamily.entity.BookBorrowOrder;
import com.literaryfamily.literaryfamily.entity.Payments;
import com.literaryfamily.literaryfamily.model.ReturnResult;
import com.literaryfamily.literaryfamily.myUtil.PageUtil;

import java.util.Date;
import java.util.List;

/**
 * 用户借阅接口
 * 调用此接口前应保证用户已登陆
 * 所有涉及读写的方法都需要抛出 WriteError 数据库读写错误异常(这个是运行时异常,只需要抛出不需要处理)
 * 此接口所有方法均不检查用户身份,应该验证身份后在进行检查
 *
 * @author 滑稽/因果报应
 */
public interface BookLeaseService {
	/**
	 * 借书方法(damageFee属性视为押金,需要支付押金后才可继续)
	 * 如果书籍为可以则将书籍状态设置为已借出,并等待用户确认取书
	 * 如果该书处于借出状态则自动转变为预约,需要同步更新上架单里面的数据
	 * 其中借阅号生成规则为(l_yyyy_MM_dd__hh_mm_ss_userId_bookId)
	 * 说明:
	 * 需要记录日志信息,将借阅时间设置为当前借阅时间,将实际借阅时间设置为null,要求提供
	 * 借阅描述或者图片证据
	 * @param bookBorrowOrder 借书信息
	 * @return 生成的订单信息
	 */
	Payments borrowABook(BookBorrowOrder bookBorrowOrder);

	/**
	 * 确认借出/取书方法
	 * 确认订单已经支付后,检查对应订单是否更新,以及其他各项信息是否对应
	 * 的上,如果全对那么久将实际借书时间设置为当前时间
	 * @param payments        支付信息
	 * @param borrow_order_id 借阅单号
	 * @param online_id       上架单号
	 * @param user_id         用户ID
	 * @return 操作结果
	 */
	BookBorrowOrder actualBorrowABook(String payments, String borrow_order_id, String online_id, Long user_id);

	/**
	 * 取消借阅(需要退还押金,仅退还实际消费金额)
	 * 通过单号去查询支付记录,将支付记录的状态设置为已退款,将借阅记录里面的状态设置为以取消
	 * @param bookBorrowOrder 完整的借阅单,根据单号查询支付记录
	 * @return 退款成功时返回对应记录
	 */
	Payments closeBorrow(BookBorrowOrder bookBorrowOrder);

	/**
	 * 获取用户借阅历史记录
	 *
	 * @param userId  查询的用户
	 * @param pageMsg 分页信息,为空时代表不进行分页,获取所有记录
	 * @return 用户的借阅记录
	 */
	List<BookBorrowOrder> getBorrowHistory(Long userId, PageUtil pageMsg);

	/**
	 * 获取某本书的全部借阅记录(包括预约的)
	 *
	 * @param bookId  需要获取的书籍
	 * @param pageMsg 分页信息,为空时代表不进行分页,获取所有记录
	 * @return 对应记录
	 */
	List<BookBorrowOrder> getBookBorrowHistory(Long bookId, PageUtil pageMsg);

	/**
	 * 还书方法,并按照: 逾期金额 * max( (实际借阅天数-允许借阅天数) ,0)
	 * 来生成逾期金订单,<0时表示不生成,优先从用户余额中扣除
	 * 流程
	 * 先将将实际归还时间设置为当前时间,然后检查是否逾期(实际借出时间-实际归还时间),将得到的毫秒数
	 * 转化为天数,得出结果向下取整(将不足1天的部分舍弃,比如1.2天->1天),得到逾期天数,天数和延期金
	 * 相乘得到违约金,生成账单,然后将账单记录,再检查用户之前是否缴纳过押金,如果无跳过这一步,如果有检查
	 * 押金是否够扣,如果够则扣除押金,如果不够则跳过这一步.然后退还剩余/完整的押金到余额中(生成退还订单并记录)
	 * 检查之前是否已经扣除了违约金,如果没有则从余额中扣除,如果余额不够就生成新的订单(不动余额)
	 *
	 * @param userId 还书用户
	 * @param bookId 还书Id
	 * @return 还书结果或者账单(? 的类型为BookBorrowOrder或者Payments)
	 */
	ReturnResult<?> returnBook(Long userId, Long bookId);

	/**
	 * 延长借阅期限
	 *
	 * @param borrowOrderId 借阅单号
	 * @param newReturnDate 新的归还日期
	 * @return 更新后的借阅单信息
	 */
	BookBorrowOrder extendBorrowPeriod(String borrowOrderId, Date newReturnDate);
}